import {
  ReactNode,
  useEffect,
  useState,
  forwardRef,
  useImperativeHandle,
  useCallback,
} from "react";
import classNames from "classnames";
import styles from "./side.module.scss";
import { createPortal } from "react-dom";

interface Props {
  // 弹层内部要渲染的内容
  children: ReactNode;
  // 弹层滑动方向
  direction: "toTop" | "toLeft" | "toRight";
}

/**
 * 1. 若要执行弹出动画, 为外层元素添加 styles.active 类名
 * 2. 如要调整弹层方向, 为内层元素添加 styles.toTop 或 styles.toLeft 或 styles.toRight 类名
 * 3. 将弹层渲染到 body 中, 而不是在哪调用就在哪渲染
 */

export interface SlideRef {
  open: () => void;
  close: () => void;
}

// 1. ref 的类型
// 2. props 的类型
export default forwardRef<SlideRef, Props>(({ children, direction }, ref) => {
  // 控制弹层是否执行动画
  const [isActive, setIsActive] = useState(false);
  // 控制弹层渲染
  const [isRender, setIsRender] = useState(false);
  // 根据 isRender 决定是否渲染弹层
  // 若要测试弹层动画, 手动修改 styles.active 对应的布尔值

  // 渲染弹层
  const open = useCallback(() => {
    setIsRender(true);
  }, []);

  // 关闭弹层
  const close = useCallback(() => {
    setIsActive(false);
    setTimeout(() => {
      setIsRender(false);
    }, 400);
  }, []);

  useImperativeHandle(ref, () => ({ open, close }), [close, open]);

  useEffect(() => {
    if (isRender) {
      setIsActive(true);
    }
  }, [isRender]);

  return isRender
    ? createPortal(
        <div
          className={classNames(styles.layer, {
            [styles.active]: isActive,
          })}
          onClick={close}
        >
          <div
            className={classNames(styles.content, {
              [styles.toTop]: direction === "toTop",
              [styles.toLeft]: direction === "toLeft",
              [styles.toRight]: direction === "toRight",
            })}
            onClick={(event) => event.stopPropagation()}
          >
            {children}
          </div>
        </div>,
        document.getElementById("portal-root")!
      )
    : null;
});
